/* DirectDraw's structures */
#ifndef DWORD
#define DWORD unsigned int
#endif

#ifndef DWORD
#define DWORD unsigned int
#endif

#ifndef MAKEFOURCC

#define MAKEFOURCC(ch0, ch1, ch2, ch3)  \ 
    ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) |  \ 
    ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )); 

#endif

struct TexSpace::DDPixelFormat
{
  GLuint size;
  GLuint flags;
  GLuint fourCC;
  GLuint bpp;
  GLuint redMask;
  GLuint greenMask;
  GLuint blueMask;
  GLuint alphaMask;
};

struct TexSpace::DDSCaps
{
  GLuint caps;
  GLuint caps2;
  GLuint caps3;
  GLuint caps4;
};

struct TexSpace::DDColorKey
{
  GLuint lowVal;
  GLuint highVal;
};

struct TexSpace::DDSurfaceDesc
{
  GLuint size;
  GLuint flags;
  GLuint height;
  GLuint width;
  GLuint pitch;
  GLuint depth;
  GLuint mipMapLevels;
  GLuint alphaBitDepth;
  GLuint reserved;
  GLuint surface;

  struct DDColorKey ckDestOverlay;
  struct DDColorKey ckDestBlt;
  struct DDColorKey ckSrcOverlay;
  struct DDColorKey ckSrcBlt;

  struct DDPixelFormat format;
  struct DDSCaps caps;

  GLuint textureStage;
};

#define FOURCC_DXT1 MAKEFOURCC('D', 'X', 'T', '1')
#define FOURCC_DXT3 MAKEFOURCC('D', 'X', 'T', '3')
#define FOURCC_DXT5 MAKEFOURCC('D', 'X', 'T', '5')

#ifndef max
static int
max (int a, int b)
{
  return ((a > b) ? a : b);
}
#endif

image_src * TexSpace::ReadDDSFile (const char *filename)
{
  struct DDSurfaceDesc ddsd;
  image_src *texinfo;
  FILE *fp;
  char magic[4];
  int mipmapFactor;
  long bufferSize, curr, end;

  /* Open the file */
  errno_t err;
  err = fopen_s (&fp,filename, "rb");
  if (err!=0)
    {
      fprintf (stderr, "error: couldn't open \"%s\"!\n", filename);
      return NULL;
    }

  /* Read magic number and check if valid .dds file */
  fread (&magic, sizeof (char), 4, fp);

  if (strncmp (magic, "DDS ", 4) != 0)
    {
      fprintf (stderr, "the file \"%s\" doesn't appear to be"
	       "a valid .dds file!\n", filename);
      fclose (fp);
      return NULL;
    }

  /* Get the surface descriptor */
  fread (&ddsd, sizeof (ddsd), 1, fp);

  texinfo = (image_src *)
    calloc (sizeof (image_src), 1);
  texinfo->width = ddsd.width;
  texinfo->height = ddsd.height;
  texinfo->numMipmaps = ddsd.mipMapLevels;
  texinfo->bpc = 1;

  switch (ddsd.format.fourCC)
    {
    case FOURCC_DXT1:
      /* DXT1's compression ratio is 8:1 */
      texinfo->format = GL_RGB;
      texinfo->internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
      mipmapFactor = 2;
      break;

    case FOURCC_DXT3:
      /* DXT3's compression ratio is 4:1 */
      texinfo->format = GL_RGBA;
      texinfo->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
      mipmapFactor = 4;
      break;

    case FOURCC_DXT5:
      /* DXT5's compression ratio is 4:1 */
      texinfo->format = GL_RGBA;
      texinfo->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
      mipmapFactor = 4;
      break;

    default:
      /* Bad fourCC, unsupported or bad format */
      fprintf (stderr, "the file \"%s\" doesn't appear to be"
	       "compressed using DXT1, DXT3, or DXT5! [%i]\n",
	       filename, ddsd.format.fourCC);
      free (texinfo);
      fclose (fp);
      return NULL;
    }

  /* Calculate pixel data size */
  curr = ftell (fp);
  fseek (fp, 0, SEEK_END);
  end = ftell (fp);
  fseek (fp, curr, SEEK_SET);
  bufferSize = end - curr;

  /* Read pixel data with mipmaps */
  texinfo->texels = (GLubyte *)malloc (bufferSize * sizeof (GLubyte));
  fread (texinfo->texels, sizeof (GLubyte), bufferSize, fp);

  /* Close the file */
  fclose (fp);
  texinfo->type=GL_UNSIGNED_BYTE;
  texinfo->bpp = texinfo->internalFormat;

  texinfo->comp = 1;
  //texinfo->numMipmaps = max_(texinfo->numMipmaps,1);
  return texinfo;
}
